package com.cqan.box.service;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javapns.notification.AppleNotificationServer;
import javapns.notification.AppleNotificationServerBasicImpl;
import javapns.notification.PayloadPerDevice;
import javapns.notification.PushNotificationPayload;
import javapns.notification.transmission.NotificationProgressListener;
import javapns.notification.transmission.NotificationThread;
import javapns.notification.transmission.NotificationThreads;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Component;

import com.cqan.box.entity.Message;
import com.cqan.service.rest.BaseRestService;
import com.google.common.collect.Lists;

@Component("sendMessageTaskService")
public class SendMessageTaskService extends BaseRestService implements Runnable {

	private static final List<Map<String, Object>> messages = Lists.newArrayList();

	@Resource(name = "messageService")
	private MessageService messageService;

	/**
	 * String message, Object keystore, String password, boolean production,
	 * Object devices
	 * 
	 * @param messages
	 */
	public void send(List<Map<String, Object>> ms) {
		messages.addAll(ms);
		start();
	}

	@Override
	public void run() {
		try {
			Iterator<Map<String, Object>> it = messages.iterator();
			while (it.hasNext()) {
				Map<String, Object> ms = (Map<String, Object>) it.next();
				Object keyStore = ms.get("keystore");
				String password =  ms.get("password").toString();
				boolean production = (Boolean) ms.get("production");
				String message =  ms.get("message").toString();
				String devices =   ms.get("devices").toString();
				Object acme =  ms.get("acme");
				Object type =  ms.get("type");
				Object sid =  ms.get("sid");
				Object appid =  ms.get("appid");
				Object tm =  ms.get("tm");
				Object oem =  ms.get("oem");
				Object sub =  ms.get("sub");
				Object boxid =  ms.get("boxid");
				Object chan =  ms.get("chan");
				try {
					// 建立与Apple服务器连接
					AppleNotificationServer server = new AppleNotificationServerBasicImpl(keyStore,password, production);
					List<PayloadPerDevice> list = new ArrayList<PayloadPerDevice>();
					PushNotificationPayload payload = new PushNotificationPayload();
					payload.addAlert(message);
					payload.addSound("default");// 声音
					payload.addBadge(1);// 图标小红圈的数值
					if (acme!=null) {
						payload.addCustomDictionary("acme",acme.toString());// 添加字典
					}
					if (tm!=null) {
						payload.addCustomDictionary("tm",tm.toString());// 添加字典
					}
					if (oem!=null) {
						payload.addCustomDictionary("oem",oem.toString());// 添加字典
					}
					if (sub!=null) {
						payload.addCustomDictionary("sub",sub.toString());// 添加字典
					}
					if (chan!=null) {
						payload.addCustomDictionary("chan",chan.toString());// 添加字典
					}
					if (boxid!=null) {
						payload.addCustomDictionary("boxid",boxid.toString());// 添加字典
					}
					PayloadPerDevice pay = new PayloadPerDevice(payload,devices);// 将要推送的消息和手机唯一标识绑定
					list.add(pay);

					NotificationThreads work = new NotificationThreads(server, list,2);//
					work.setListener(DEBUGGING_PROGRESS_LISTENER);// 对线程的监听，一定要加上这个监听
					work.start(); // 启动线程
					work.waitForAllThreads();// 等待所有线程启动完成

				} catch (Exception e) {
					e.printStackTrace();
				}
				
				Message m = new Message();
				m.setClient(appid.toString());
				m.setCtime(Calendar.getInstance().getTime());
				m.setMessage(message);
				m.setSid(sid.toString());
				m.setToken(devices);
				m.setType(StringUtils.defaultIfEmpty((String)type, "0"));
				logger.debug("send message {}", m);
				messageService.add(m);
				it.remove();
			}
		} catch (Exception e) {
			logger.debug("send message error {}", e.getMessage());
			e.printStackTrace();
		}

	}

	public static final NotificationProgressListener DEBUGGING_PROGRESS_LISTENER = new NotificationProgressListener() {
		public void eventThreadStarted(NotificationThread notificationThread) {
			logger.debug("   [EVENT]: thread #"+ notificationThread.getThreadNumber() + " started with "+ " devices beginning at message id #"+ notificationThread.getFirstMessageIdentifier());
		}

		public void eventThreadFinished(NotificationThread thread) {
			logger.debug("   [EVENT]: thread #" + thread.getThreadNumber() + " finished: pushed messages #" + thread.getFirstMessageIdentifier() + " to " + thread.getLastMessageIdentifier() + " toward " + " devices");
		}

		public void eventConnectionRestarted(NotificationThread thread) {
			logger.debug("   [EVENT]: connection restarted in thread #"
					+ thread.getThreadNumber() + " because it reached "
					+ thread.getMaxNotificationsPerConnection()
					+ " notifications per connection");
		}

		public void eventAllThreadsStarted(
				NotificationThreads notificationThreads) {
			logger.debug("   [EVENT]: all threads started: "
					+ notificationThreads.getThreads().size());
		}

		public void eventAllThreadsFinished(
				NotificationThreads notificationThreads) {
			logger.debug("   [EVENT]: all threads finished: "
					+ notificationThreads.getThreads().size());
		}

		public void eventCriticalException(
				NotificationThread notificationThread, Exception exception) {
			logger.debug("   [EVENT]: critical exception occurred: "
					+ exception);
		}
	};
	
	private void start() {
		Thread t = new Thread(this);
		t.start();
	}

}
